package com.yt.user.common.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yt.common.constant.CommonParameter;
import com.yt.common.utils.WebUtils;
import com.yt.db.utils.RedisTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @Description ：
 * @Author ： 解风
 * @Date ： 2017/11/28 09:39
 */
@Slf4j
@Configuration
public class ApiHandlerInterceptor implements HandlerInterceptor {


    @Autowired
    private RedisTokenUtil redisTokenUtil;

    /**
     * controller 执行之前调用
     * 只有返回true才会继续向下执行，返回false取消当前请求
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", "*");//解决跨域
        //响应头设置
        response.setHeader("Access-Control-Allow-Headers", "Authorization,Content-type,Accept,X-Requested-With,sessionId,source,appVersion,Origin");
        //响应类型
        response.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");

        WebUtils.setHeadParams(request);
        String ip = WebUtils.getClientIP(request);
        CommonParameter.getHeadParamsBO().setClientIp(ip);

        JSONObject json = new JSONObject();
        if(handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            json.put("methodName", method.getDeclaringClass().getName() + "." + method.getName());
        }
        json.put("startTime", System.currentTimeMillis());
        json.put("ip:", ip);
        json.put("url:", request.getRequestURI());
        json.put("params", JSON.toJSONString(request.getParameterMap()));
        CommonParameter.getHeadParamsBO().setBodyParams(JSON.toJSONString(json));

        String requestUrl = request.getRequestURI();



        // just for debug
        //测试阶段关闭签名
//        if(!ExcludeApisConstant.getInstance().isSignExist(requestUrl)){
//            if(!SignUtils.valiSignature(request)){
//                Result result = new Result(CodeEnum.FAIL_100004);
//                WebUtils.outPrint(response, JSON.toJSONString(result));
//                return false;
//            }
//        }
//
//        if (!ExcludeApisConstant.getInstance().isExist(requestUrl)) {//
//            Result result = sessionService.isSessionExpired(CommonParameter.getHeadParamsBO().getSessionId());
//            if(!result.success()){
//                WebUtils.outPrint(response, JSON.toJSONString(result));
//                return false;
//            }
//            return true;
//        }


        // 1. 从请求头中获取 Authorization 字段（格式：Bearer token）
        String authorization = request.getHeader("Authorization");
        if(!StringUtils.isEmpty(authorization)){
            // 2. 验证 Authorization 格式
            if (authorization == null || !authorization.startsWith("Bearer ")) {
                response.setStatus(401); // 未授权
                return false; // 拦截请求，不继续向下执行
            }

            // 3. 提取 Token（去掉 "Bearer " 前缀）
            String token = authorization.substring(7);
            String userName = redisTokenUtil.validateToken(token);
            boolean isValid = redisTokenUtil.isTokenValid(token);
            long time = redisTokenUtil.getTokenRemainingTime(token);
            if(!isValid){
                response.setStatus(401); // Token 无效或过期
                return false;
            }
        }
        return true;
    }
//    public void wireOpetionLog(HttpServletRequest request, UserInfoDTO userInfoDTO, UserLoginDTO sysUserDTO){
//        JSONObject json = new JSONObject();
//        json.put("ip:", WebUtils.getClientIP(request));
//        json.put("url:", request.getRequestURI());
//        //写日志
//        UserOperationLogDTO dto = new UserOperationLogDTO();
//        dto.setId(ymlConfig.getPkId());
//        dto.setClassName(WebUtils.getClientIP(request));
//        dto.setMethodName(WebUtils.getClientIP(request));
//        dto.setCreateTime(new Date());
//        dto.setUpdateTime(new Date());
//        dto.setResultMsg(request.getRequestURI());
//        dto.setUserAccount(sysUserDTO.getAccount());
//        dto.setUserName(userInfoDTO.getName());
//        dto.setUserId(userInfoDTO.getId());
//        userOperationLogService.insert(dto);
//    }


    /**
     * controller 执行之后调用
     * 这个方法只会在当前这个Interceptor的preHandle方法返回值为true的时候才会执行。
     * postHandle是进行处理器拦截用的，它的执行时间是在处理器进行处理之后，也就是在Controller的方法调用之后执行，
     * 但是它会在DispatcherServlet进行视图的渲染之前执行，也就是说在这个方法中你可以对ModelAndView进行操作。
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        if(handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
//            long start_time = (Long) request.getAttribute("start_time");
//            long end_time = System.currentTimeMillis();
//            long consume_time = end_time - start_time;//消耗时间
//
//            log.info("postHandle访问目标:" + method.getDeclaringClass().getName() + "." + method.getName() + "，消耗时间：" + consume_time + " ms");

//            CommonParameter.plintInfo();
        }
//        log.info("postHandle-response.getStatus()：" + response.getStatus());
    }

    /**
     * 该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行,
     * 该方法将在整个请求完成之后，也就是DispatcherServlet渲染了视图执行，这个方法的主要作用是用于清理资源的，
     * 当然这个方法也只能在当前这个Interceptor的preHandle方法的返回值为true时才会执行。
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //wangjx7.21 取消日志
//        logger.info("afterCompletion-response.getStatus()：" + response.getStatus());
//        if(handler instanceof HandlerMethod ) {
//            HandlerMethod handlerMethod = (HandlerMethod) handler;
//            Method method = handlerMethod.getMethod();
//
//            logger.info("afterCompletion-getShortLogMessage：" + handlerMethod.getShortLogMessage());
//        log.info("afterCompletion-访问目标：结束"+request.getRequestURI());
//        }

        CommonParameter.plintInfo();
    }


//    private void addApiLog(String ip, String methodPath, String url, Long consumeTime){
//        SysApiLogSaveBO sysApiLogSaveBO = new SysApiLogSaveBO();
//        sysApiLogSaveBO.setIp(ip);//ip
//        sysApiLogSaveBO.setMethodPath(methodPath);//方法路径
//        sysApiLogSaveBO.setUrl(url);//访问地址
//        sysApiLogSaveBO.setConsumeTime(consumeTime); //消耗时间
//        iSysApiLogService.add(sysApiLogSaveBO);
//    }

}
